This directory contains two versions of essentially the same tool.
The larger one, udevmod, is a regular long-running never-exiting service
for general use. The second, smaller one (devinit) is meant for initrd
use only and does normally exit.

Both tools run modprobe whenever kernel reports a new modaliased device.
udevmod also implements some libudev compatibility behavior (to allow
running unmodified X and Weston atop of it) and minimalistic device node
chmod/chown which has no use atm and should be removed at some point.


Initrd specifics
~~~~~~~~~~~~~~~~
udevmod is a service, that is, it does not exit. This mode of operation
does not fit well within initrd, which is a transitional startup stage,
so whatever's running there has to exit at some point.

Atop of that, large part of the code in udevmod makes no sense in initrd.
There should be no libudev clients there, no need to chmod devices and so on.

So instead, the second tool (devinit) was introduced to do exactly what's
needed for initrd and nothing more.


Device renaming
~~~~~~~~~~~~~~~
In current Linux device names are unreliable and often meaningless.
One has to sift through /sys or even probe the device to figure out what
exactly say /dev/input/event19 refers to. It would be better to name devices
in meaningful name, say /dev/input/ptr-stick instead of nondescript
/dev/input/event19, and /dev/input/keyboard instead of /dev/input/event0.

Implementing this idea well seems to be impossible.

Lots of device-specific information is typically available through /sys.
Renaming a node in /dev does not change any nodes in /sys.
Finding and renaming all nodes in /sys is not easy, and probably not feasible.
Handling /dev nodes named differently than /sys names may be possible but not
always, and it is tricky/confusing.

Persistent device names would make sense if they could be used as regular
file names, for instance for scripting or in config files. This isn't the case.
Pretty any way of using device names in scripts or configs would result in
racy application that won't handle hot-plugging well. Those that will handle
hot-plugging, would not need persistent device names most likely.


Non-privileged access to devices
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The reason for udevd to chmod or chown device nodes is to allow non-privileged
users to use certain devices. So far, it looks like it is possible to get away
without relying on this at all in minibase.

There are very few subsystems that the users may need to access at all.

ALSA (raw or via libasound) requires non-privileged device access, but direct
access to ALSA is a bad idea anyway and with a sound server running only the
server itself needs the devices.

Inputs and block devices must be requested via privileged services (vtmux and
mountd respectively). This seems to be the best way to handle this problem
in general within minibase. A device manager that grands access to certain
devices on request, possibly also locking or ensuring non-interference between
the clients.

Sometimes it makes sense to let users access serial ports. However, serial
ports are TTYs, figuring out which TTYs are serial ports is tricky, some may
need privileged locking anyway (e.g. to avoid users sniffing on pppd), so it
really calls for another privileged device manager.

DRIs (non-mastering) remain perhaps the only kind of devices for which group
based restrictions maybe make sense.


Device tagging and libinput
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The original udevd has the ability to pass device configuration to clients.
Input devices get the following keys added to their events to indicate which
event they can generate:

    ID_INPUT=1
    ID_INPUT_KEY=1
    ID_INPUT_KEYBOARD=1

Additionally udevd can transmit XKB configuration for keyboards the same way,
by adding keys to the event.

The idea was apparently that udevd is better equipped for querying and matching
physical device data, so all per-device configuration would be stored in udevd
configs and the clients will only get it through udev events.

It's a horrible idea that makes no sense given the way udev works (one-sided
event broadcast), existing implementation are racy in a subtle way, and the
whole thing only really works if the clients are homogeneous -- like say all
of them use libinput and xkbcommon. Because Freedesktop.

The problem with this is that Xorg udev code as well as udev code within
libinput will simply ignore input devices not tagged ID_INPUT. In addition,
Xorg will not apply MatchIs{Keyboard,Pointer,Touchpad} from its config unless
the devices are tagged the right way.

Solely for compatibility with braindamaged Freedesktop stuff, udevmod from
minibase does provide these keys. This is seen as temporary solution until
the crap gets patched out of all relevant clients. My current opinion on this
is that the clients know better how to match the devices they use, and have
better ways of storing their own configuration than shoving it into udevd.d.


Technical background
~~~~~~~~~~~~~~~~~~~~
To listen to udev events, clients open PF_NETLINK socket and subscribe either
UDEV_MGRP_KERNEL (bit 0, mask (1<<0)) or UDEV_MGRP_LIBUDEV (bit 1, mask (1<<1))
groups when bind()ing it. UDEV_MGRP_KERNEL if for kernel-generated messages,
UDEV_MGRP_LIBUDEV is for those coming from udevd.

udev messages do not follow common netlink conventions. Kernel message are
packets of 0-terminated strings that look like this (\0 replaced with \n):

        add@/devices/platform/i8042/serio1/input/input13/event10
        ACTION=add
        DEVPATH=/devices/platform/i8042/serio1/input/input13/event10
        SUBSYSTEM=input
        MAJOR=13
        MINOR=74
        DEVNAME=input/event10

Messages from udevd on UDEV_MGRP_LIBUDEV use a different format format,
private to udevd/libudev, which carries the same data with prepended binary
header. Because, you know, Freedesktop. Luckily libudev accepts raw kernel
messages even when listening on UDEV_MGRP_LIBUDEV, so minibase only uses
the kernel format.

Check ../../temp/udev/udevdump.c, a simple tool that dumps all incoming
messages, to see how it all works on the client side. Events for a particular
device can be triggered at any moment like this:

  echo add > /sys/devices/platform/i8042/serio1/input/input13/event10/uevent

This will force the kernel to repeat the "add" event above. Beware the event
will be processes just like any real kernel event. Some libudev clients may
try to do unexpected things in response.
